import { isFunction } from "../shared/index.js";
import { activeEffect, ReactiveEffect } from "./effect.js";
import { trackEffects, triggerEffects } from "./handler.js";

class ComputedRefImpl {
  constructor(getter, setter) {
    this._value = undefined;
    this._dirty = true;
    this.__v_isRef = true;
    this.getter = getter;
    this.setter = setter;
    this.dep = new Set();
    // 计算属性是一个effect，会让 getter 中的属性去收集这个 effect
    this.effect = new ReactiveEffect(getter, () => {
      //   ...
      this._dirty = true; // 让计算属性标记为脏值
      triggerEffects(this.dep);
    });
  }

  get value() {
    if (activeEffect) {
      //   value => [effect]
      trackEffects(this.dep);
    }
    if (this._dirty) {
      this._dirty = false;
      // 取值让 getter 执行拿到返回值，作为计算属性旳值
      this._value = this.effect.run();
    }
    return this._value;
  }

  set value(val) {
    // 修改时出发 setter 即可
    this.setter(val);
  }
}

export function computed(getterOrOptions) {
  const isGetter = isFunction(getterOrOptions);
  let getter;
  let setter;

  if (isGetter) {
    getter = getterOrOptions;
    setter = () => {
      console.log("computed is readonly");
    };
  } else {
    getter = getterOrOptions.get;
    setter = getterOrOptions.set;
  }

  return new ComputedRefImpl(getter, setter);
}
